<?php

namespace app\admin\process;

use app\admin\model\system\SystemDept;
use app\admin\model\system\SystemDeptLeader;
use app\admin\model\system\SystemPost;
use app\admin\model\system\SystemUser;
use app\admin\model\system\SystemUserPost;
use app\admin\model\system\SystemUserRole;
use app\common\service\SignService;
use GuzzleHttp\Client;
use support\Log;
use think\facade\Db;

class autoSyncOAData {
    private $uri;
    public function run($args)
    {
        $this->uri = env('OA_URI') . '/api/sync';
        try {
            $this->deptLeadersData = [];
            $this->deleteLeaderIds = [];
            // 同步部门数据
            $this->syncDept();
            // 同步岗位数据
            $this->syncPost();
            // 同步用户数据
            $this->syncUser();
            // 同步部门领导
            $this->syncDeptLeader();
        } catch (\Exception $e) {
            Log::error('自动同步OA数据失败: ' . $e->getMessage());
        }
    }

    private function call($endpoint, $data = [])
    {
        $payload = [
            'timestamp' => strval(time()),
            'nonce'     => uniqid(),
            'data'      => $data,
        ];
        $payload['sign'] = SignService::sign($payload['data'], $payload['timestamp'], $payload['nonce']);
        $payload['data'] = json_encode($payload['data']);
        $client  = new Client();
        $res     = $client->post($this->uri . $endpoint, [
            'headers' => ['Content-Type' => 'application/json'],
            'json'    => $payload,
        ]);
        $body = json_decode($res->getBody()->getContents(), true);
        return $body['data'] ?? [];
    }

    /*
     * 同步部门数据
     */
    private function syncDept()
    {
        $departmentData = $this->call('/get_department');
        if (empty($departmentData)) return false;
        Db::startTrans();
        try {
            $systemDept = new SystemDept();
            $localDept = $systemDept->where('source_type', 1)->column('id', 'oa_dept_id');
            $deptMap = $localDept;
            $insertData = [];
            foreach ($departmentData as $row) {
                if (isset($localDept[$row['id']])) continue;
                $insertData[] = [
                    'parent_id'   => $row['pid'],
                    'name'        => $row['title'],
                    'status'      => empty($row['status']) ? 2 : 1,
                    'sort'        => $row['sort'],
                    'remark'      => $row['remark'],
                    'oa_dept_id'  => $row['id'],
                    'source_type' => 1,
                    'create_time' => formatTime($row['create_time'] ?? 0),
                    'update_time' => formatTime($row['update_time'] ?? 0),
                    'created_by' => 1,
                    'updated_by' => 1,
                    'leader_ids'   => $row['leader_ids'],
                ];
            }

            if (!empty($insertData)) {
                foreach ($insertData as $item) {
                    $_leaderIds = $item['leader_ids'] ?? '';
                    unset($item['leader_ids']);
                    $deptId = $systemDept->insertGetId($item);
                    $deptMap[$item['oa_dept_id']] = $deptId;
                    $this->deptLeadersData[] = [
                        'dept_id' => $deptId,
                        'user_id' => $_leaderIds,
                    ];
                }
            }
            // 更新部门数据
            $updateData = [];
            foreach ($departmentData as $row) {
                $localId = $deptMap[$row['id']] ?? null;
                if (!$localId) continue;
                $this->deleteLeaderIds[] = $localId;
                $updateData[] = [
                    'id'         => $localId,
                    'parent_id'  => $deptMap[$row['pid']] ?? 0,
                    'name'       => $row['title'],
                    'status'     => empty($row['status']) ? 2 : 1,
                    'sort'       => $row['sort'],
                    'remark'     => $row['remark'],
                    'update_time'=> formatTime($row['update_time']),
                ];
                $this->deptLeadersData[] = [
                    'dept_id' => $localId,
                    'user_id' => $row['leader_ids'],
                ];
            }
            if (!empty($updateData)) {
                $systemDept->saveAll($updateData);
            }
            $oaIds = array_column($departmentData, 'id');
            $deleteIds = array_diff(array_keys($deptMap), $oaIds);
            if (!empty($deleteIds)) {
                $localIds = [];
                foreach ($deleteIds as $id) {
                    $localIds[] = $deptMap[$id] ?? 0;
                }
                SystemDeptLeader::whereIn('dept_id', $localIds)->delete();
                $systemDept->destroy($localIds);
            }
            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            Log::error('同步部门数据失败: ' . $e->getMessage());
        }
        return false;
    }

    /*
     * 同步岗位数据
     */
    private function syncPost()
    {
        $postData = $this->call('/get_position');
        if (empty($postData)) return false;

        return Db::transaction(function () use ($postData) {
            $systemPost = new SystemPost();
            $allPost = $systemPost->where('source_type', 1)->column('id', 'oa_post_id');
            $saveData = [];
            if (!empty($postData)) {
                foreach ($postData as $row) {
                    $item = [
                        'oa_post_id'  => $row['id'],
                        'name'        => $row['title'],
                        'code'        => 'POST_'.$row['id'],
                        'sort'        => $row['id'],
                        'status'      => 1,
                        'remark'      => '',
                        'source_type' => 1,
                        'create_time' => formatTime($row['create_time'] ?? 0),
                        'update_time' => formatTime($row['update_time'] ?? 0),
                        'created_by'  => 1,
                        'updated_by'  => 1,
                    ];
                    if (isset($allPost[$row['id']])) {
                        $item['id'] = $allPost[$row['id']];
                    }
                    $saveData[] = $item;
                }
            }
            if (!empty($saveData)) {
                $systemPost->saveAll($saveData, true);
            }
        });
    }

    /*
     * 同步用户数据
     */
    private function syncUser()
    {
        $userData = $this->call('/get_userlist');
        if (empty($userData)) return false;

        return Db::transaction(function () use ($userData) {
            $systemUser = new SystemUser();
            $allUserList = $systemUser->where('source_type', 1)->column('id', 'oa_user_id');

            $postList = SystemPost::where('source_type', 1)->column('id', 'oa_post_id');

            $deptList = SystemDept::where('source_type', 1)->column('id', 'oa_dept_id');

            $systemUserPost = new SystemUserPost();
            $systemUserRole = new SystemUserRole();
            $addData = []; $updateData = []; $userPostData = []; $userPostDeleteIds = [];

            if (!empty($userData)) {
                foreach ($userData as $row) {
                    if ($row['username'] == 'admin') continue;
                    $item = [
                        'username' => $row['username'],
                        'password' => '',
                        'oa_password' => $row['pwd'],
                        'oa_salt' => $row['salt'],
                        'user_type' => 100,
                        'nickname' => $row['name'],
                        'phone' => $row['mobile'],
                        'email' => $row['email'],
                        'dept_id' => $deptList[$row['did']] ?? 0,
                        'status' => empty($row['status']) ? 2 : 1,
                        'oa_user_id'  => $row['id'],
                        'source_type' => 1,
                        'create_time' => formatTime($row['create_time'] ?? 0),
                        'update_time' => formatTime($row['update_time'] ?? 0),
                        'created_by'  => 1,
                        'updated_by'  => 1,
                    ];

                    $postId = $postList[$row['position_id']] ?? 0;
                    // 更新用户和岗位 system_user_post
                    if (isset($allUserList[$row['id']])) {
                        $item['id'] = $allUserList[$row['id']];
                        $updateData[] = $item;
                        $userPostData[] = [
                            'user_id' => $item['id'],
                            'post_id' => $postId,
                        ];
                        $userPostDeleteIds[] = $item['id'];
                    } else {
                        $item['post_id'] = $postId;
                        $addData[] = $item;
                    }
                }
            }

            if (!empty($updateData)) {
                $systemUser->saveAll($updateData);
            }
            $userRoleData = [];
            if (!empty($addData)) {
                foreach ($addData as $item) {
                    $postId = $item['post_id'] ?? 0;
                    unset($item['post_id']);
                    $userId = $systemUser->insertGetId($item);
                    if ($postId) {
                        $userPostData[] = [
                            'user_id' => $userId,
                            'post_id' => $postId,
                        ];
                    }
                    $userRoleData[] = [
                        'user_id' => $userId,
                        'role_id' => 6,
                    ];
                }
            }
            if (!empty($userPostDeleteIds)) {
                $systemUserPost->whereIn('user_id', $userPostDeleteIds)->delete();
            }
            if (!empty($userPostData)) {
                $systemUserPost->saveAll($userPostData);
            }
            if (!empty($userRoleData)) {
                $systemUserRole->saveAll($userRoleData);
            }
        });
    }

    private function syncDeptLeader()
    {
        $departmentData = $this->call('/get_department');
        if (empty($departmentData)) return false;

        $userMap = SystemUser::where('source_type', 1)->column('id', 'oa_user_id');
        $deptMap = SystemDept::where('source_type', 1)->column('id', 'oa_dept_id');
        $saveData = [];
        foreach ($departmentData as $dept) {
            foreach (explode(',', $dept['leader_ids'] ?? '') as $uid) {
                if (!empty($userMap[$uid])) {
                    $saveData[] = ['dept_id' => $deptMap[$dept['id']] ?? 0, 'user_id' => $userMap[$uid] ?? 0];
                }
            }
        }

        if (!empty($saveData)) {
            try {
                Db::transaction(function () use ($saveData) {
                    SystemDeptLeader::whereIn('dept_id', array_unique(array_column($saveData, 'dept_id')))->delete();
                    SystemDeptLeader::insertAll($saveData);
                });
            } catch (\Exception $e) {
                Log::error('同步部门负责人数据失败: ' . $e->getMessage());
            }
        }
        return false;
    }
}